package com.ossjk.config.shiro;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.Condition;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.ossjk.core.util.Constant;
import com.ossjk.core.util.JwtTokenUtil;
import com.ossjk.core.vo.ResponseBean;
import com.ossjk.oa.system.entity.Department;
import com.ossjk.oa.system.entity.EmployeePost;
import com.ossjk.oa.system.entity.Post;
import com.ossjk.oa.system.entity.Token;
import com.ossjk.oa.system.service.IDepartmentService;
import com.ossjk.oa.system.service.IEmployeePostService;
import com.ossjk.oa.system.service.IEmployeeService;
import com.ossjk.oa.system.service.IPermissionService;
import com.ossjk.oa.system.service.IPostService;
import com.ossjk.oa.system.service.ITokenService;

/**
 * JwtFilter:jwt过滤器来作为shiro的过滤器
 *
 * @author zhangxiaoxiang
 * @date: 2019/07/12
 */
public class JwtFilter extends BasicHttpAuthenticationFilter implements Filter {

	public Logger log = LoggerFactory.getLogger(JwtFilter.class);
	private JwtTokenUtil jwtTokenUtil;
	private IEmployeeService iEmployeeService;
	private ITokenService iTokenService;
	private IPermissionService iPermissionService;
	private IPostService iPostService;
	private IDepartmentService iDepartmentService;
	private IEmployeePostService iEmployeePostService;

	public JwtFilter(JwtTokenUtil jwtTokenUtil, IEmployeeService iEmployeeService, IEmployeePostService iEmployeePostService, ITokenService iTokenService, IPermissionService iPermissionService, IPostService iPostService, IDepartmentService iDepartmentService) {
		this.jwtTokenUtil = jwtTokenUtil;
		this.iEmployeeService = iEmployeeService;
		this.iEmployeePostService = iEmployeePostService;
		this.iTokenService = iTokenService;
		this.iPermissionService = iPermissionService;
		this.iPostService = iPostService;
		this.iDepartmentService = iDepartmentService;
	}

	/**
	 * 执行登录
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@Override
	protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
		HttpServletRequest httpServletRequest = (HttpServletRequest) request;
		HttpServletResponse httpServletResponse = (HttpServletResponse) response;
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");
		String tokenStr = jwtTokenUtil.getToken(httpServletRequest);
		ResponseBean responseBean = null;
		try {
			JwtToken jwtToken = new JwtToken(tokenStr);
			// 提交给realm进行登入，如果错误他会抛出异常并被捕获
			getSubject(request, response).login(jwtToken);
			// 如果没有抛出异常则代表登入成功，返回true
			return true;
		} catch (NoTokenException e) {
			// token失效
			responseBean = new ResponseBean(Constant.RESPONSE_CODE_NOLOGIN, Constant.RESPONSE_MSG_NOLOGIN);
		} catch (TokenFlushException e) {
			Token token = new Token();
			// token刷新
			String uid = jwtTokenUtil.getUserId(tokenStr);
			String newTokenStr = jwtTokenUtil.generalToken(uid, jwtTokenUtil.getSubject(tokenStr));
			token.setUid(uid);
			token.setDuration(jwtTokenUtil.getTokenTimeOut(newTokenStr));
			token.setToken(newTokenStr);
			List<String> codes = iPermissionService.selectCodeByEid(uid);
			Map expression = new HashMap();
			expression.put("perssion", codes);
			// 岗位id
			Wrapper wrapper2 = Condition.create().eq("eid", uid);
			EmployeePost employeePost = iEmployeePostService.selectOne(wrapper2);
			expression.put(Constant.REQUEST_PID_KEY, employeePost.getPid());
			// 部门id
			Post post = iPostService.selectById(employeePost.getPid());
			expression.put(Constant.REQUEST_DID_KEY, post.getDid());
			Wrapper wrapper3 = Condition.create();

			List dsub = iDepartmentService.selectSubIdByPid(post.getDid());
			dsub.add(post.getDid());
			expression.put(Constant.REQUEST_DSUB_KEY, dsub);
			Wrapper wrapper4 = Condition.create();
			List<Post> posts = iPostService.selectList(wrapper4);
			// List psub = new ArrayList();
			// psub.add(employeePost.getPid());
			List psub = iPostService.selectSubIdByPid(post.getId());
			psub.add(post.getId());
			expression.put(Constant.REQUEST_PSUB_KEY, psub);

			token.setExpression(JSON.toJSONString(expression));
			iTokenService.insertNewToken(token);
			responseBean = new ResponseBean(Constant.RESPONSE_CODE_REFRESH, Constant.RESPONSE_MSG_REFRESH, newTokenStr);
		} catch (AuthenticationException e) {
			// token失效
			responseBean = new ResponseBean(Constant.RESPONSE_CODE_NOLOGIN, Constant.RESPONSE_MSG_NOLOGIN);
		}
		String json = JSON.toJSONString(responseBean);
		log.warn("拦截请求：" + httpServletRequest.getRequestURI() + ",原因：" + json);
		response.setContentType("application/json");
		PrintWriter out = response.getWriter();
		out.print(json);
		out.flush();
		out.close();
		return false;

	}

	/**
	 * 执行登录认证
	 *
	 * @param request
	 * @param response
	 * @param mappedValue
	 * @return
	 */
	@Override
	protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
		try {
			return executeLogin(request, response);
			// return true;有一篇博客这里直接返回true是不正确的,在这里我特别指出一下
		} catch (Exception e) {
			log.error("拦截器报错", e);
			return false;
		}
	}

}
